package com.easylinkin.linkappapi.project.service.impl;

import cn.hutool.core.date.DateUnit;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.utils.DateUtil;
import com.easylinkin.linkappapi.openapi.util.HttpClientUtil;
import com.easylinkin.linkappapi.project.entity.Project;
import com.easylinkin.linkappapi.project.entity.dto.ProjectFromEnterprise;
import com.easylinkin.linkappapi.project.mapper.ProjectMapper;
import com.easylinkin.linkappapi.project.service.ProjectService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.sevice.LinkappTenantService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author TongJie
 * @since 2020-04-16
 */
@Service
@Slf4j
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements ProjectService {


    @Resource
    private RedissonClient redisson;
    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;
    @Resource
    private LinkappTenantService linkappTenantService;

    @Value("${edu.apiUrl:http://localhost:15004/api}")
    private String apiUrl;



    @Override
    public String getIdByName(String name) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("project_name", name);
        queryWrapper.select("id");
        List<Project> projects = baseMapper.selectList(queryWrapper);
        if (projects.isEmpty()) {
            throw new BusinessException("由" + name + "找不到项目");
        }
        if (projects.size() > 1) {
            throw new BusinessException("由" + name + "找到多个项目");
        }
        return projects.get(0).getId();

    }

    public void addProject2(Project project) {
        for (int i = 0; i < 50; i++) {
            Date date = new Date();
            List<Project> projectList = selectProjects(project);
            if (projectList.size() >= 40) {
                return;
            } else {
                project.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                project.setProjectName(project.getId());
                project.setCreateTime(date);
                project.setModifyTime(date);
                project.setModifier("1");
                project.setCreator("1");
                insertProject(project);
            }
        }
    }

    /**
     * 并发测试 无用代码
     */
    @Override
    public void addProject(Project project) {
        RLock redissonLock = redisson.getLock("add_project_lock");
        if (redissonLock.tryLock()) {
            try {
                addProject2(project);

            } finally {
                redissonLock.unlock();
            }
        }

    }


    /**
     * 并发测试 无用代码
     */
    public List<Project> selectProjects(Project project) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("project_code", project.getProjectCode());
        List<Project> list = baseMapper.selectList(queryWrapper);
        return list;
    }

    /**
     * 并发测试 无用代码
     */
    public void insertProject(Project project) {
        save(project);
    }

    /**
     * <p>定时任务测试 测试-分布式锁  redisson分布式锁</p>
     * <p>测试ok:两个节点不会在同一时刻执行一次任务，</p>
     */
//    @Scheduled(cron = "0/5 * * * * ?")
    public void jobtest() {
        RLock redissonLock = redisson.getLock("job_test_lock");
        if (redissonLock.tryLock()) {
            try {
                System.out.println("job test---" + DateUtil.getYYYYMMDDHHMMSSDate(new Date()));
            } finally {
                redissonLock.unlock();
            }
        }
    }


    @Override
    public ProjectFromEnterprise getInfo(String tenantId) {
        if(StringUtils.isBlank(tenantId)){
            tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        }
        LinkappTenant tenant = linkappTenantService.getOneById(tenantId);
        Assert.notNull(tenant, "查询到租户为空");
        String projectId = tenant.getProjectId();
        String url = apiUrl + "/enterpriseOpenApi/dashBoard/getProjectById?id=" + projectId;
        HttpGet httpGet = new HttpGet(url);
        log.info("请求 getInfo url:" + url);
        String str = HttpClientUtil.doGet(httpGet);
        log.info("请求 getInfo:" + str);
        ProjectFromEnterprise project = JSON.parseObject(str, ProjectFromEnterprise.class);

        if (null != project.getProjectStatus()) {
            List<Integer> projectBeingStatusList = Arrays.asList(0, 1, 2, 3);
            List<Integer> projectDoneStatusList = Arrays.asList(4, 5);
            if (projectBeingStatusList.contains(project.getProjectStatus())) {
                // 1. 对于项目类型为，“在建项目”、“中标项目”、“施工准备”、“停工缓建”类型的项目：计划竣工日期-当前日期作为剩余工期；当剩余工期为负时，显示为已延期
                if (null == project.getCompletionTime()) {
                    return project;
                }
                Date startTime = cn.hutool.core.date.DateUtil.beginOfDay(new Date());
                Date endTime = cn.hutool.core.date.DateUtil.beginOfDay(project.getCompletionTime());
                Long surplusDay = cn.hutool.core.date.DateUtil
                        .between(startTime, endTime, DateUnit.DAY, false);// endTime - startTime
                project.setSurplusDay(surplusDay);
            }
            if (projectDoneStatusList.contains(project.getProjectStatus())) {
                project.setSurplusDay(0L);
            }
        }
        return project;
    }

    @Override
    public ProjectFromEnterprise updateInfo(ProjectFromEnterprise projectFromEnterprise) {
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        LinkappTenant tenant = linkappTenantService.getOneById(tenantId);
        Assert.notNull(tenant, "查询到租户为空");
        String projectId = tenant.getProjectId();

        Assert.notNull(projectFromEnterprise.getId(), "参数id为空");
        Assert.isTrue((projectFromEnterprise.getId() + "").equals(projectId), "与当前用户所在项目不一致");

        String url = apiUrl + "/enterpriseOpenApi/dashBoard/updateProjectById";
        HttpPost httpPost = new HttpPost(url);
        log.info("请求 getInfo url:" + url);

        httpPost.setEntity(new StringEntity(JSON.toJSONString(projectFromEnterprise), ContentType.APPLICATION_JSON));
        String str = HttpClientUtil.doPost(httpPost);
        log.info("请求 getInfo:" + str);

        ProjectFromEnterprise res = JSON.parseObject(str, ProjectFromEnterprise.class);
        // 如果 企业端正常返回 则更新租户的经纬度和location信息
        if (res != null) {
            UpdateWrapper<LinkappTenant> updateWrapper = new UpdateWrapper<>();
            if (projectFromEnterprise.getLongitude() != null) {
                updateWrapper.set("longitude", projectFromEnterprise.getLongitude());
            }
            if (projectFromEnterprise.getLongitude() != null) {
                updateWrapper.set("latitude", projectFromEnterprise.getLatitude());
            }
            if (projectFromEnterprise.getLocation() != null) {
                updateWrapper.set("location", projectFromEnterprise.getLocation());
            }
            updateWrapper.eq("project_id", projectId);
            linkappTenantService.update(updateWrapper);
        }
        return res;
    }

}
